package org.example.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.Result;
import org.example.handler.GlobalExceptionHandler;
import org.example.mapper.*;
import org.example.model.vo.LoginUser;
import org.example.service.LoginService;
import org.example.sso.model.entity.PermissionDO;
import org.example.sso.model.entity.RolePermissionDO;
import org.example.sso.model.entity.UserDO;
import org.example.sso.model.entity.UserRoleDO;
import org.example.utils.JwtUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    private final StringRedisTemplate stringRedisTemplate;
    private final UserMapper userMapper;
    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;
    private final PermissionMapper permissionMapper;
    private final RolePermissionMapper rolePermissionMapper;

    private final PasswordEncoder passwordEncoder;

    @Override
    public Result<String> login(String username, String password) {
        LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserDO::getUserName, username);
        UserDO userDO = userMapper.selectOne(queryWrapper);
        if (userDO == null) {
            throw new GlobalExceptionHandler.BusinessException("user.entity.empty", "用户不存在");
        }
        if (!passwordEncoder.matches(password, userDO.getPassword())) {
            throw new GlobalExceptionHandler.BusinessException("user.entity.password", "密码错误");
        }

        LoginUser loginUser = new LoginUser(userDO);


        setAuthorities(loginUser, userDO.getId());

        String token = JwtUtil.createJWT(JSONUtil.toJsonStr(loginUser));

        stringRedisTemplate.opsForValue().set("token:" + token, token, Duration.ofMillis(JwtUtil.JWT_TTL));
        return Result.success(token);
    }

    private void setAuthorities(LoginUser loginUser, Long userId) {
        List<UserRoleDO> userRoleDOs = userRoleMapper.selectList(
                new LambdaQueryWrapper<UserRoleDO>()
                        .eq(UserRoleDO::getUserId, userId)
        );
        if (userRoleDOs != null && !userRoleDOs.isEmpty()) {
            List<RolePermissionDO> rolePermissionDOS = rolePermissionMapper.selectList(new LambdaQueryWrapper<RolePermissionDO>()
                    .in(RolePermissionDO::getRoleId, userRoleDOs.stream().map(UserRoleDO::getRoleId).distinct().collect(Collectors.toList()))

            );
            if (rolePermissionDOS != null && !rolePermissionDOS.isEmpty()) {
                List<PermissionDO> permissionDOS = permissionMapper.selectList(new LambdaQueryWrapper<PermissionDO>()
                        .in(PermissionDO::getId, rolePermissionDOS.stream().map(RolePermissionDO::getPermissionId).distinct().collect(Collectors.toList())));
                loginUser.setPermissions(permissionDOS.stream().map(PermissionDO::getPermissionCode).distinct().collect(Collectors.toList()));;
            }
        }
    }

    @Override
    public Result<String> logout(HttpServletRequest request) {
        String authorization = request.getHeader("Authorization");
        if (authorization != null && authorization.startsWith("Bearer ")) {
            String token = authorization.substring(7);
            String tokenKey = "token:" + token;
            stringRedisTemplate.delete(tokenKey);
            return Result.success("登出成功");
        }
        throw new GlobalExceptionHandler.BusinessException("sys:user:logout:fail", "token 为空");
    }
}
